home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / SBZR_AUX.C < prev    next >
C/C++ Source or Header  |  1991-05-19  |  10KB  |  272 lines

  1. /******************************************************************************
  2. * SBzr-Aux.c - Bezier surface auxilary routines.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #ifdef __MSDOS__
  8. #include <stdlib.h>
  9. #endif /* __MSDOS__ */
  10.  
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "cagd_loc.h"
  15.  
  16. /* Define some marcos to make some of the routines below look better. They  */
  17. /* calculate the index of the U, V point of the control mesh in Points.        */
  18. #define DERIVED_SRF(U, V)    CAGD_MESH_UV(DerivedSrf, U, V)
  19. #define RAISED_SRF(U, V)    CAGD_MESH_UV(RaisedSrf, U, V)
  20. #define SRF(U, V)        CAGD_MESH_UV(Srf, U, V)
  21.  
  22. /******************************************************************************
  23. * Given a bezier surface - subdivide it into two at given parametric value.   *
  24. * Returns pointer to first surface in a list of two srfs (subdivided ones).   *
  25. * The subdivision is exact result of subdivising the surface one row/col at a *
  26. * time, using the Bezier curve subdivision.                      *
  27. ******************************************************************************/
  28. CagdSrfStruct *BzrSrfSubdivAtParam(CagdSrfStruct *Srf, CagdRType t,
  29.                             CagdSrfDirType Dir)
  30. {
  31.     int Row, Col,
  32.     ULength = Srf -> ULength,
  33.     VLength = Srf -> VLength;
  34.     CagdCrvStruct *Crv, *LCrv, *RCrv;
  35.     CagdSrfStruct
  36.     *RSrf = BzrSrfNew(ULength, VLength, Srf ->PType),
  37.     *LSrf = BzrSrfNew(ULength, VLength, Srf ->PType);
  38.  
  39.     switch (Dir) {
  40.     case CAGD_CONST_U_DIR:
  41.         for (Row = 0; Row < VLength; Row++) {
  42.         Crv = BzrSrfCrvFromMesh(Srf, Row, CAGD_CONST_V_DIR);
  43.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  44.         RCrv = LCrv -> Pnext;
  45.         CagdCrvToMesh(LCrv, Row, CAGD_CONST_V_DIR, LSrf);
  46.         CagdCrvToMesh(RCrv, Row, CAGD_CONST_V_DIR, RSrf);
  47.  
  48.         CagdCrvFree(Crv);
  49.         CagdCrvFree(LCrv);
  50.         CagdCrvFree(RCrv);
  51.         }
  52.         break;
  53.     case CAGD_CONST_V_DIR:
  54.         for (Col = 0; Col < ULength; Col++) {
  55.         Crv = BzrSrfCrvFromMesh(Srf, Col, CAGD_CONST_U_DIR);
  56.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  57.         RCrv = LCrv -> Pnext;
  58.         CagdCrvToMesh(LCrv, Col, CAGD_CONST_U_DIR, LSrf);
  59.         CagdCrvToMesh(RCrv, Col, CAGD_CONST_U_DIR, RSrf);
  60.  
  61.         CagdCrvFree(Crv);
  62.         CagdCrvFree(LCrv);
  63.         CagdCrvFree(RCrv);
  64.         }
  65.         break;
  66.     default:
  67.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  68.         break;
  69.     }
  70.  
  71.     LSrf -> Pnext = RSrf;
  72.     return LSrf;
  73. }
  74.  
  75. /******************************************************************************
  76. * Return a new surface, identical to the original but with one degree higher  *
  77. * in the given direction.                              *
  78. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:    *
  79. *               i        k-i                          *
  80. * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1).              *
  81. *               k         k                          *
  82. * This is applied to all rows/cols of the surface.                  *
  83. ******************************************************************************/
  84. CagdSrfStruct *BzrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  85. {
  86.     CagdBType
  87.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  88.     int i, j, Row, Col,
  89.     ULength = Srf -> ULength,
  90.     VLength = Srf -> VLength,
  91.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  92.     CagdSrfStruct
  93.     *RaisedSrf = NULL;
  94.  
  95.     switch (Dir) {
  96.     case CAGD_CONST_U_DIR:
  97.         RaisedSrf = BzrSrfNew(ULength, VLength + 1, Srf -> PType);
  98.  
  99.         for (Col = 0; Col < ULength; Col++) {
  100.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  101.             RaisedSrf -> Points[j][RAISED_SRF(Col, 0)] =
  102.                Srf -> Points[j][SRF(Col, 0)];
  103.  
  104.         for (i = 1; i < VLength; i++)                /* Q(i). */
  105.             for (j = IsNotRational; j <= MaxCoord; j++)
  106.             RaisedSrf -> Points[j][RAISED_SRF(Col, i)] =
  107.                 Srf -> Points[j][SRF(Col, i - 1)] *
  108.                                  (i / ((CagdRType) VLength)) +
  109.                 Srf -> Points[j][SRF(Col, i)] *
  110.                      ((VLength - i) / ((CagdRType) VLength));
  111.  
  112.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  113.             RaisedSrf -> Points[j][RAISED_SRF(Col, VLength)] =
  114.             Srf -> Points[j][SRF(Col, VLength - 1)];
  115.             }
  116.         break;
  117.     case CAGD_CONST_V_DIR:
  118.         RaisedSrf = BzrSrfNew(ULength + 1, VLength, Srf -> PType);
  119.  
  120.         for (Row = 0; Row < VLength; Row++) {
  121.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  122.             RaisedSrf -> Points[j][RAISED_SRF(0, Row)] =
  123.                Srf -> Points[j][SRF(0, Row)];
  124.  
  125.         for (i = 1; i < ULength; i++)                /* Q(i). */
  126.             for (j = IsNotRational; j <= MaxCoord; j++)
  127.             RaisedSrf -> Points[j][RAISED_SRF(i, Row)] =
  128.                 Srf -> Points[j][SRF(i - 1, Row)] *
  129.                                  (i / ((CagdRType) ULength)) +
  130.                 Srf -> Points[j][SRF(i, Row)] *
  131.                          ((ULength - i) / ((CagdRType) ULength));
  132.  
  133.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  134.             RaisedSrf -> Points[j][RAISED_SRF(ULength, Row)] =
  135.             Srf -> Points[j][SRF(ULength - 1, Row)];
  136.         }
  137.         break;
  138.     default:
  139.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  140.         break;
  141.     }
  142.  
  143.     return RaisedSrf;
  144. }
  145.  
  146. /******************************************************************************
  147. * Return a new surface equal to the derived surface in the direction Dir.     *
  148. * A test is made to make sure the original surface is not rational.          *
  149. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:    *
  150. * Q(i) = (k - 1) * P(i+1) - P(i), i = 0 to k-2.                      *
  151. * This is applied to all rows/cols of the surface.                  *
  152. ******************************************************************************/
  153. CagdSrfStruct *BzrSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  154. {
  155.     CagdBType
  156.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  157.     int i, j, Row, Col,
  158.     ULength = Srf -> ULength,
  159.     VLength = Srf -> VLength,
  160.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  161.     CagdSrfStruct
  162.         *DerivedSrf = NULL;
  163.  
  164.  
  165.     switch (Dir) {
  166.     case CAGD_CONST_U_DIR:
  167.         if (!IsNotRational || VLength < 3)
  168.         FATAL_ERROR(CAGD_ERR_RAT_LIN_NO_SUPPORT);
  169.  
  170.         DerivedSrf = BzrSrfNew(ULength, VLength - 1, Srf -> PType);
  171.  
  172.         for (Col = 0; Col < ULength; Col++)
  173.         for (i = 0; i < VLength - 1; i++)
  174.             for (j = IsNotRational; j <= MaxCoord; j++)
  175.             DerivedSrf -> Points[j][DERIVED_SRF(Col, i)] =
  176.                             (VLength - 1) *
  177.                 (Srf -> Points[j][SRF(Col, i + 1)] -
  178.                  Srf -> Points[j][SRF(Col, i)]);
  179.         break;
  180.     case CAGD_CONST_V_DIR:
  181.         if (!IsNotRational || ULength < 3)
  182.         FATAL_ERROR(CAGD_ERR_RAT_LIN_NO_SUPPORT);
  183.  
  184.         DerivedSrf = BzrSrfNew(ULength - 1, VLength, Srf -> PType);
  185.  
  186.         for (Row = 0; Row < VLength; Row++)
  187.         for (i = 0; i < ULength - 1; i++)
  188.             for (j = IsNotRational; j <= MaxCoord; j++)
  189.             DerivedSrf -> Points[j][DERIVED_SRF(i, Row)] =
  190.                             (ULength - 1) *
  191.                 (Srf -> Points[j][SRF(i + 1, Row)] -
  192.                  Srf -> Points[j][SRF(i, Row)]);
  193.         break;
  194.     default:
  195.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  196.         break;
  197.     }
  198.  
  199.     return DerivedSrf;
  200. }
  201.  
  202.  
  203. /******************************************************************************
  204. * Evaluate the tangent to a surface at a given point and given direction.     *
  205. ******************************************************************************/
  206. CagdVecStruct *BzrSrfTangent(CagdSrfStruct *Srf, CagdRType u, CagdRType v,
  207.                              CagdSrfDirType Dir)
  208. {
  209.     CagdVecStruct
  210.     *Tangent = NULL;
  211.     CagdCrvStruct *Crv;
  212.  
  213.     switch (Dir) {
  214.     case CAGD_CONST_V_DIR:
  215.         Crv = BzrSrfCrvFromSrf(Srf, v, Dir);
  216.         Tangent = BzrCrvTangent(Crv, u);
  217.         CagdCrvFree(Crv);
  218.         break;
  219.     case CAGD_CONST_U_DIR:
  220.         Crv = BzrSrfCrvFromSrf(Srf, u, Dir);
  221.         Tangent = BzrCrvTangent(Crv, v);
  222.         CagdCrvFree(Crv);
  223.         break;
  224.     default:
  225.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  226.         break;
  227.     }
  228.  
  229.     return Tangent;
  230. }
  231.  
  232. /******************************************************************************
  233. * Evaluate the normal of a surface at a given point.                  *
  234. ******************************************************************************/
  235. CagdVecStruct *BzrSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  236. {
  237.     static CagdVecStruct Normal;
  238.     CagdVecStruct *V, T1, T2;
  239.  
  240.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_U_DIR);
  241.     CAGD_COPY_VECTOR(T1, *V);
  242.  
  243.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_V_DIR);
  244.     CAGD_COPY_VECTOR(T2, *V);
  245.  
  246.     /* The normal is the cross product of T1 and T2: */
  247.     Normal.Vec[0] = T1.Vec[1] * T2.Vec[2] - T1.Vec[2] * T2.Vec[1];
  248.     Normal.Vec[1] = T1.Vec[2] * T2.Vec[0] - T1.Vec[0] * T2.Vec[2];
  249.     Normal.Vec[2] = T1.Vec[0] * T2.Vec[1] - T1.Vec[1] * T2.Vec[0];
  250.  
  251.     CAGD_NORMALIZE_VECTOR(Normal);            /* Normalize the vector. */
  252.  
  253.     return &Normal;
  254. }
  255.  
  256. /******************************************************************************
  257. * Convert a Bezier srf into Bspline srf by adding two open knot vectors.      *
  258. ******************************************************************************/
  259. CagdSrfStruct *CnvrtBezier2BsplineSrf(CagdSrfStruct *Srf)
  260. {
  261.     CagdSrfStruct *BspSrf = CagdSrfCopy(Srf);
  262.  
  263.     BspSrf -> UOrder = BspSrf -> ULength;
  264.     BspSrf -> VOrder = BspSrf -> VLength;
  265.     BspSrf -> UKnotVector = BspKnotUniformOpen(BspSrf -> ULength,
  266.                             BspSrf -> UOrder, NULL);
  267.     BspSrf -> VKnotVector = BspKnotUniformOpen(BspSrf -> VLength,
  268.                             BspSrf -> VOrder, NULL);
  269.     BspSrf -> GType = CAGD_SBSPLINE_TYPE;
  270.     return BspSrf;
  271. }
  272.